package util

import (
	"crypto/md5"
	"fmt"
	"github.com/leekchan/accounting"
	"github.com/shopspring/decimal"
	"gpt-api/pkg/constant"
	"math"
	"math/rand"
	"strconv"
	"strings"
	"time"

	"github.com/spf13/viper"
)

func Md5(str string) string {
	h := md5.New()
	h.Write([]byte(str))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func IsDev() bool {
	return viper.GetString("env") == "dev"
}

func VersionNumTransfer(version string) int64 {
	if version == "" {
		return 0
	}

	tmp := strings.Split(version, ".")
	if len(tmp) != 2 && len(tmp) != 3 {
		panic("invalid version string")
	}

	if len(tmp) == 2 {
		tmp = append(tmp, "0")
	}

	first, _ := strconv.Atoi(tmp[0])
	second, _ := strconv.Atoi(tmp[1])
	third, _ := strconv.Atoi(tmp[2])

	versionNum := 1000000*first + 1000*second + third

	return int64(versionNum)
}

func RandInt(min int, max int) int {
	return min + rand.Intn(max-min)
}

func RandStr(length int) string {
	charset := "abcdefghlijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST"
	b := make([]byte, length)
	for i := range b {
		index := RandInt(0, len(charset)-1)
		b[i] = charset[index]
	}

	return string(b)
}

func FirstUpper(s string) string {
	if s == "" {
		return ""
	}
	return strings.ToUpper(s[:1]) + s[1:]
}

// CoinDecimalFormat
// decimalOriginStr 原值
// precision 精度
func CoinDecimalFormat(decimalOriginStr string, precision int, isPrice bool) (s string) {
	original, _ := decimal.NewFromString(decimalOriginStr)

	// border 格式化临界值
	borderNum := "1"
	border, _ := decimal.NewFromString(borderNum)

	// 当金额大于Bn时
	if original.GreaterThanOrEqual(border) {
		// 大于等于1的时候，精度强制转换为2
		precision = 2

		acPrecision := precision
		if isPrice {
			acPrecision = 2
		} else {
			acPrecision = 2
		}
		ac := accounting.Accounting{Symbol: "", Thousand: ",", Precision: acPrecision} // 注意该库不支持解析string

		bn := decimal.NewFromInt(1000000000)
		if original.GreaterThanOrEqual(bn) {
			tmp := original.Div(bn)
			s = ac.FormatMoney(tmp)
			s = fmt.Sprintf("%s%s", s, "Bn")
			return
		}

		m := decimal.NewFromInt(1000000)
		if original.GreaterThanOrEqual(m) {
			tmp := original.Div(m)
			s = ac.FormatMoney(tmp)
			s = fmt.Sprintf("%s%s", s, "M")
			return
		}

		tmp := original.Round(int32(precision))
		s = ac.FormatMoney(tmp)
		return
	} else {
		s = original.Round(int32(precision)).String()
		return
	}
}

func RandomCode() string {
	if IsDev() {
		return "1234"
	} else {
		r := rand.New(rand.NewSource(time.Now().UnixNano()))
		return fmt.Sprintf("%04d", 10000-r.Intn(9999))
	}
}

func DecimalPadZero(origin string, precision int, padding int) string {
	originDecimal, _ := decimal.NewFromString(origin)
	str := originDecimal.Round(int32(precision)).String()
	tmp := strings.Split(str, ".")

	zero := ""
	if len(tmp) > 1 {
		zero = tmp[1]
	}

	for i := len(zero); i < padding; i++ {
		zero += "0"
	}

	return tmp[0] + "." + zero
}

func GetPricePrecision(platform, position string) int {
	// Android/IOS 详情页价格12位 其他8位
	// H5详情页价格12位 排行榜12位  其他8位
	// PC 首页之外12位

	precision := 8

	switch platform {
	case "H5":
		if position == constant.PrecisionPositionOfRankings {
			precision = constant.CoinPrecisionOf12
		}
	case "PC":
		if position != constant.PrecisionPositionOfHome {
			precision = constant.CoinPrecisionOf12
		}
	}

	return precision
}

func GetZoneStr(zone string) (zoneStr string) {
	return "UTC"
	if zone == "" {
		return "UTC"
	}

	tmp, _ := strconv.ParseFloat(zone, 32)
	if tmp > 0 {
		zoneStr = "UTC-" + strconv.FormatFloat(math.Abs(tmp), 'f', -1, 64)
	} else {
		zoneStr = "UTC+" + strconv.FormatFloat(math.Abs(tmp), 'f', -1, 64)
	}

	return zoneStr
}

func RoundNum() string {
	return fmt.Sprintf("%v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000000))
}

//GetFormatAmount 格式化金额
func GetFormatAmount(num int64) string {
	str := strconv.FormatInt(num, 10)
	for len(str) < 12 {
		str = "0" + str
	}
	return str
}
